{
    /**
     * 游戏操控器
     */
    class GameControlView extends Laya.Sprite {
        constructor() {
            super();
            this.size(Laya.stage.width, Laya.stage.height);
            this.actions = null;
            this.active = false;
            this.battleInfo = null;
            this.gameStatusInfo = null;
            this.killBlueMediator = null;
            this.killRedMediator = null;
            this.moveRokerControl = null;
            this.aimRokerControl = null;
            this.btnCancle = null;
            this.skillChargeMediator = null;
            this.skillRokerControl = null;
            //颜色滤镜，红色
            this.redFilter = new Laya.ColorFilter([
                1, 0, 0, 0, 0, //R
                0, 0, 0, 0, 0, //G
                0, 0, 0, 0, 0, //B
                0, 0, 0, 1, 0, //A
            ]);
            this.timeLabel = null;
            this.initComponent();
        }

        //删除监听
        destoryEvent() {
            this.skillChargeMediator && this.skillChargeMediator.destoryEvent();

            this.moveRokerControl && this.moveRokerControl.destoryEvent();
            this.aimRokerControl && this.aimRokerControl.destoryEvent();
            this.skillRokerControl && this.skillRokerControl.destoryEvent();
            this.killBlueMediator && this.killBlueMediator.destoryEvent();
            this.killRedMediator && this.killRedMediator.destoryEvent();

            Laya.stage.off(Laya.Event.MOUSE_DOWN, this, this.handleRoker);

            Sail.io.unregister(this.actions);
        }

        initComponent() {
            let commonCounter = new Laya.Label;
                commonCounter.fontSize = 300;
                commonCounter.height = 500;
                commonCounter.centerX = 0;
                commonCounter.centerY = 0;
                commonCounter.color = '#ffffff';
                commonCounter.stroke = 4;
                commonCounter.visible = false;
            this.commonCounter = commonCounter;

            //顶部倒计时组件
            this.battleInfo = new ui.Room.Com.BattleInfoUI();
            this.addChild(this.battleInfo);

            //右上角状态
            this.gameStatusInfo = new ui.Room.Com.GameStatusInfoUI();
            this.addChild(this.gameStatusInfo);

            //蓝方击杀
            var killBlue = new ui.Room.Com.KillBlueUI();
            killBlue.alpha = 0;
            this.killBlueMediator = new KillMediator(killBlue);
            this.killBlueMediator.init('kill.blue.show');
            this.addChild(killBlue);

            //红方击杀
            var killRed = new ui.Room.Com.KillRedUI();
            killRed.alpha = 0;
            this.killRedMediator = new KillMediator(killRed);
            this.killRedMediator.init('kill.red.show');
            this.addChild(killRed);

            //移动摇杆
            var moveRoker = new ui.Room.Com.RockerMoveUI();
            this.addChild(moveRoker);
            //射击摇杆
            var aimRoker = new ui.Room.Com.RockerAimUI();
            this.addChild(aimRoker);

            //移动摇杆控制器
            this.moveRokerControl = new Control.Room.RokerMediator();
            this.moveRokerControl.init(moveRoker, 1, true);
            // this.moveRokerControl.on('roker_move', this, this.moveHandle);

            //射击摇杆控制器
            this.aimRokerControl = new Control.Room.RokerMediator();
            this.aimRokerControl.init(aimRoker, 1);
            this.aimRokerControl.on('roker_execute', this, this.aimHandle);

            //摇杆取消按钮
            this.btnCancle = new Laya.Button('res/game/scene/btn_cancle.png', "");
            this.btnCancle.stateNum = 1;
            this.btnCancle.visible = false;
            this.btnCancle.alpha = 0.5;
            this.addChild(this.btnCancle);
            this.btnCancle.on(Laya.Event.MOUSE_OVER, this, () => { this.btnCancle.alpha = 1 });
            this.btnCancle.on(Laya.Event.MOUSE_OUT, this, () => { this.btnCancle.alpha = 0.5 });
            this.btnCancle.on(Laya.Event.MOUSE_UP, this, this.cancleRoker);

            //技能蓄力图标
            var skillCharge = new ui.Room.Com.SkillChargeUI();
            skillCharge.mouseEnabled = false;
            this.addChild(skillCharge);
            this.skillChargeMediator = new SkillChargeMediator(skillCharge);
            this.skillChargeMediator.on('completed', this, this.showSkillRoker);
            this.skillChargeMediator.on('reset', this, this.hideSkillRoker);

            //技能摇杆
            var skillRoker = new ui.Room.Com.RockerSkillUI();
            skillRoker.visible = false;
            this.addChild(skillRoker);

            //技能摇杆控制器
            this.skillRokerControl = new Control.Room.RokerMediator();
            this.skillRokerControl.init(skillRoker, 0);
            this.skillRokerControl.on('roker_execute', this, this.skillHandle);

            this.addChild(this.commonCounter);
            Laya.stage.on(Laya.Event.MOUSE_DOWN, this, this.handleRoker);

            this.actions = {
                "control.roker.start": this.showRokerCancle,
                "control.roker.do": this.hideRokerCancle,
                "info.set": this.setGameInfo,

                "role.die" () {
                    this.commonCounter.visible = true;
                    function loop (total) {
                        total--;
                        if(total < 0){
                            this.commonCounter.visible = false;
                            return;
                        }
                        this.commonCounter.text = `重生：${total}s`;
                        Laya.timer.once(1000, this, loop, [total]);
                    };
                    loop.call(this, 6);
                },

                "battleScore" (data) {
                    this.battleInfo.scoreBlue.text = data[0];
                    this.battleInfo.scoreRed.text = data[1];
                },
                "battleUser" (data) {
                    if(data.kid == GM.user_id){
                        this.gameStatusInfo.killNum.text = (this.gameStatusInfo.killNum.text | 0) + 1;
                    }
                    if(data.did == GM.user_id){
                        this.gameStatusInfo.deathNum.text = (this.gameStatusInfo.deathNum.text | 0) + 1;
                    }
                }
            };
            Sail.io.register(this.actions, this);
        }

        //删除指示器
        clearIndicator() {
            //普通攻击指示器
            if (this.indicator && this.indicator.parent) {
                this.indicator.destroy();
            }
            //技能指示器
            if (this.skillIndicator && this.skillIndicator.parent) {
                this.skillIndicator.destroy();
            }
            this.indicator = null;
            this.skillIndicator = null;
        }

        init(data) {
            this._data = data;
            //清除指示器
            this.clearIndicator();

            //添加技能蓄力槽和摇杆的技能图标
            this.addSkillIcon('charge', 'fire');
            this.addSkillIcon('roker', 'fire');

            //添加指示器
            this.indicator = this.createIndicator(data.normal.indicator);
            this.skillIndicator = this.createIndicator(data.skill.indicator);

            this.indicator.visible = false;
            this.skillIndicator.visible = false;

            //自适应界面
            this.onResize();
        }

        //根据数据创建指示器
        createIndicator(data, isNoBullet = false) {
            let sp = new Laya.Sprite();
            sp.alpha = 0.3;
            let color = isNoBullet ? 'ff3000' : 'fcff00';
            //data.type 1-矩形指示器 2-扇形指示器
            if (data.type == 1) {
                sp.graphics.drawRect(0, -data.width / 2, data.range, data.width, color);
            } else {
                sp.graphics.drawPie(0, 0, data.range, -data.width / 2, data.width / 2, color);
            }
            sp.status = isNoBullet;
            this.addChildAt(sp, 0);
            return sp;
        }

        /**
         * 添加技能图标
         * @param {*} type 'charge'-蓄力图标 'roker'-摇杆
         * @param {*} name 技能图标名称
         */
        addSkillIcon(type, name) {
            let skin = type == 'charge' ? this.skillChargeMediator._skin : this.skillRokerControl._skin.point;
            // skin.removeChildAt(1);
            var skillIcon = new Laya.Image('res/game/skill/' + type + '_' + name + '.png');
            skillIcon.anchorX = 0.5;
            skillIcon.anchorY = 0.5;
            skillIcon.mouseEnabled = false;
            skillIcon.pos(skin.width / 2, skin.height / 2);
            skin.addChild(skillIcon);
        }

        //自适应
        onResize() {
            let sx = Laya.stage.width / GAME_CONFIG.WIDTH;
            let sy = Laya.stage.height / GAME_CONFIG.HEIGHT;

            let moveRoker = this.moveRokerControl._skin;
            let aimRoker = this.aimRokerControl._skin;
            let skillCharge = this.skillChargeMediator._skin;
            let skillRoker = this.skillRokerControl._skin;

            this.battleInfo.pos(Laya.stage.width / 2, 10 * sy);
            this.gameStatusInfo.pos(Laya.stage.width - 25 * sx, 25 * sy);
            this.killBlueMediator._skin.pos(0, Laya.stage.height / 6);
            this.killRedMediator._skin.pos(Laya.stage.width, Laya.stage.height / 6);

            moveRoker.pos(200 * sx + moveRoker.width / 2, Laya.stage.height - moveRoker.height / 2 - 60 * sy);
            aimRoker.pos(Laya.stage.width - aimRoker.width / 2 - 200 * sx, Laya.stage.height - aimRoker.height / 2 - 60 * sy);

            this.btnCancle.pos(Laya.stage.width - this.btnCancle.width - 200 * sx, Laya.stage.height / 2 - aimRoker.height / 2 - 75 * sy);

            skillCharge.pos(aimRoker.x - aimRoker.width / 2 - skillRoker.width / 2 - 40 * sx, Laya.stage.height - skillRoker.height / 2 - 60 * sy);
            skillRoker.pos(skillCharge.x, skillCharge.y);

            this.moveRokerControl.setInitPos();
            this.aimRokerControl.setInitPos();
        }

        countDown (total) {
            var str = "";
            var m = 0;
            var s = total % 60;
            if(total > 60) {
                m = total / 60 | 0;
            }
            
            this.battleInfo.rest.text = `${m < 10 ? `0${m}` : m}:${s < 10 ? `0${s}` : s}`;
            total--;
            if(total < 0){return;}
            Laya.timer.once(1000, this, this.countDown, [total]);
        }

        //预留给倒计时使用
        start(data){
            if(data == 0){
                this.commonCounter.visible = false;
                this.countDown(180);
                return;
            }
            // if(!this.timeLabel){
            //     this.timeLabel = new Laya.Label();
            //     this.timeLabel.fontSize = 500;
            //     this.timeLabel.centerX = 0;
            //     this.timeLabel.centerY = 0;
            //     this.timeLabel.color = '#ffffff';
            //     this.timeLabel.stroke = 4;
            //     this.addChild(this.timeLabel);
            // }
            this.commonCounter.visible = true;
            this.commonCounter.text = `${data}s`;
        }

        //显示指示器
        showSkillRoker() {
            this.skillChargeMediator._skin.visible = false;
            this.skillRokerControl._skin.visible = true;
        }

        //隐藏指示器
        hideSkillRoker() {
            this.skillChargeMediator._skin.visible = true;
            this.skillRokerControl._skin.visible = false;
        }

        //显示取消按钮
        showRokerCancle() {
            this.btnCancle.visible = true;
            this.btnCancle.alpha = 0.5;
        }

        //隐藏取消按钮
        hideRokerCancle() {
            this.btnCancle.visible = false;
            this.btnCancle.alpha = 0.5;
        }

        //检测启用哪个摇杆
        handleRoker(e) {
            //摇杆不可用
            if (!this.active) {
                return;
            }
            //点击在界面左半边启用移动摇杆
            if (Laya.stage.mouseX < Laya.stage.width / 2) {
                this.moveRokerControl.start(e);
                //技能摇杆及瞄准摇杆都未启用
            } else if (!this.skillRokerControl.active && !this.aimRokerControl.active) {
                //鼠标点击到技能摇杆启用技能摇杆
                if (this.skillRokerControl._skin.visible && this.skillRokerControl._skin.hitTestPoint(Laya.stage.mouseX, Laya.stage.mouseY)) {
                    this.skillRokerControl.start(e);
                    Sail.io.publish('control.roker.start', 'skill');
                    //未点击到技能摇杆且点击在界面右下半边启用瞄准摇杆
                } else if (Laya.stage.mouseY > Laya.stage.height / 2) {
                    this.aimRokerControl.start(e);
                    Sail.io.publish('control.roker.start', 'attack');
                }
            }
        }
        
        //取消摇杆的使用
        cancleRoker(e) {
            this.aimRokerControl.cancle(e);
            this.skillRokerControl.cancle(e);
        }

        /**
         * 显示指示器
         * @param {*} p {x:0, y:0} 指示器显示位置
         * @param {*} isNoBullet 是否还有弹匣数
         */
        showIndicator(p, isNoBullet) {
            let roker = this.aimRokerControl.active ? this.aimRokerControl : this.skillRokerControl;
            let speed = roker.speed;
            if (speed == 0) {
                return;
            }
            let direct = roker.direct;
            let angle = Math.atan2(direct[1], direct[0]) * 180 / Math.PI;
            let target = this.aimRokerControl.active ? this.indicator : this.skillIndicator;

            this.indicatorActive = true;
            //若是滤镜降帧太厉害也可使用重绘的方式
            if(target.status != isNoBullet){
                target.destroy();
                if(this.aimRokerControl.active){
                    this.indicator = this.createIndicator(this._data.normal.indicator, isNoBullet);
                    target = this.indicator;
                }else{
                    this.skillIndicator = this.createIndicator(this._data.skill.indicator, isNoBullet);
                    target = this.skillIndicator;
                }
            }
            target.pos(p.x, p.y);
            target.rotation = angle;
            target.status = isNoBullet;
            target.visible = true;
        }

        //隐藏指示器
        hideIndicator() {
            this.indicator.visible = false;
            this.skillIndicator.visible = false;
        }

        //行走摇杆移动
        moveHandle() {
            Sail.io.publish('control.move');
        }

        //攻击
        aimHandle() {
            Sail.io.publish('control.roker.do', 'attack');
        }
        
        //放技能
        skillHandle() {
            Sail.io.publish('control.roker.do', 'skill');
        }

        setGameInfo(data) {
            this.gameStatusInfo.killNum.text = data.killNum;
            this.gameStatusInfo.deathNum.text = data.deathNum;
        }
    }

    Sail.class(GameControlView, "Com.Room.GameControlView");

    class SkillChargeMediator extends Laya.EventDispatcher {
        constructor(skin) {
            super();
            this._skin = skin;
            this.startX = skin.width / 2;
            this.startY = skin.height / 2;
            this.radius = skin.width / 2 - 5;
            this.startAngle = -90;

            this.sp = new Laya.Sprite();
            this._skin.addChildAt(this.sp, 1);

            this.power = 0;

            Sail.io.register({
                "skill.set.power": this.setPower,
                "skill.add.power": this.addPower
            }, this);
        }

        destoryEvent() {
            Sail.io.unregister({
                "skill.set.power": this.setPower,
                "skill.add.power": this.addPower
            }, this);
        }

        /**
         * 重置能量值百分比
         * @param {*} val 0-1
         */
        setPower(val) {
            this.power = val;
            this.do();
        }

        addPower(val) {
            this.power += val;
            this.do();
        }

        //绘制蓄力槽
        do() {
            this.sp.graphics.clear();
            this.sp.graphics.drawPie(this.startX, this.startY, this.radius, this.startAngle, this.startAngle + this.power * 360, "#f4bd00");
            if (this.power >= 1) {
                this.event('completed');
            }else if(this.power == 0){
                this.event('reset');
            }
        }

        getPower() {
            return this.power;
        }
    }

    class KillMediator {
        constructor(skin) {
            this._skin = skin;
            this._action = {};
        }

        destoryEvent(){
            Sail.io.unregister(this._action, this);
        }

        init(cmd) {
            this._action[cmd] = this.show;
            Sail.io.register(this._action, this);
        }

        //显示击杀面板
        show(data) {
            Laya.Tween.clearAll(this._skin);
            this._skin.alpha = 1;
            this._skin.nameKid.text = data.kid.ue;
            this._skin.nameDid.text = data.did.ue;
            this._skin.score.text = data.kid.sc;
            this._skin.avatarKid.skin = `res/role_icon/icon_${ data.kid.icon }.png`;
            this._skin.avatarDid.skin = `res/role_icon/icon_${ data.did.icon }.png`;

            Laya.timer.once(1500, this, this.hide, [], true);
        }

        hide() {
            Laya.Tween.to(this._skin, { alpha: 0 }, 2000, Laya.Ease.linearIn);
        }
    }
}